package com.cah.project.module.generate.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.StrUtil;
import com.cah.project.core.domain.out.PageList;
import com.cah.project.exception.BusinessException;
import com.cah.project.module.constant.ProjectConstant;
import com.cah.project.module.generate.domain.bo.GenTableBO;
import com.cah.project.module.generate.domain.converter.GenConverter;
import com.cah.project.module.generate.domain.entity.GenTableColumnEntity;
import com.cah.project.module.generate.domain.entity.GenTableEntity;
import com.cah.project.module.generate.domain.vo.GenTableColumnInfo;
import com.cah.project.module.generate.domain.vo.GenTableInfo;
import com.cah.project.module.generate.domain.vo.in.GenTableQuery;
import com.cah.project.module.generate.domain.vo.out.DbTableColumnList;
import com.cah.project.module.generate.domain.vo.out.DbTableList;
import com.cah.project.module.generate.domain.vo.out.GenTableList;
import com.cah.project.module.generate.service.IGenService;
import com.cah.project.module.generate.service.IGenTableColumnService;
import com.cah.project.module.generate.service.IGenTableService;
import com.cah.project.module.generate.service.helper.GenHelper;
import com.cah.project.module.generate.util.VelocityInitializer;
import com.cah.project.module.generate.util.VelocityUtils;
import lombok.RequiredArgsConstructor;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.StringWriter;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * 功能描述: 代码生成 服务实现 <br/>
 */
@Service
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class GenServiceImpl implements IGenService {

    private final IGenTableService genTableService;
    private final IGenTableColumnService genTableColumnService;
    private final GenHelper genHelper;

    @Override
    public GenTableInfo getGenTableById(String id) {
        GenTableEntity genTableEntity = genTableService.getById(id);
        // 子表另说。。。
        return GenConverter.INSTANCE.toGenTableInfo(genTableEntity);
    }

    @Override
    public List<GenTableColumnInfo> selectGenTableColumnInfoByTableId(Long tableId) {
        List<GenTableColumnEntity> genTableColumnEntityList = genTableColumnService.getByTableId(tableId);
        return GenConverter.INSTANCE.toGenTableColumnInfoList(genTableColumnEntityList);
    }

    @Override
    public PageList<GenTableList> pageList(GenTableQuery query) {
        return genTableService.pageList(query);
    }

    @Override
    public PageList<DbTableList> dbPageList(GenTableQuery query) {
        return genTableService.dbPageList(query);
    }

    @Override
    public void saveInfo(GenTableInfo info) {
        // 校验
        genHelper.check(info);
        // 保存 生成表定义
        GenTableEntity genTableEntity = GenConverter.INSTANCE.toGenTableEntity(info);
        genTableService.saveOrUpdate(genTableEntity);
        // 保存 生成表字段定义
        List<GenTableColumnEntity> columnEntityList = GenConverter.INSTANCE.toGenTableColumnEntityList(info.getColumns());
        genTableColumnService.saveOrUpdateBatch(columnEntityList);
    }

    @Override
    public void saveImport(String tableNames) {
        // 使用“,”分割tableNames
        List<String> tableNameList = ListUtil.toList(StrUtil.split(tableNames, ProjectConstant.DOU_HAO_EN));
        // 查询数据库中表信息
        List<DbTableList> dbTableList = genTableService.selectDbList(tableNameList);
        if(CollectionUtil.isNotEmpty(dbTableList)) {
            // 查询 字段信息
            List<DbTableColumnList> dbTableColumnList = genTableColumnService.selectDbList(tableNameList);
            // 填充定义表默认信息
            List<GenTableEntity> genTableEntityList = genHelper.initGenTableEntityList(dbTableList);
            // 批量保存 定义表信息
            genTableService.saveBatch(genTableEntityList);
            Map<String, GenTableEntity> tableEntityMap = genTableEntityList.stream().collect(Collectors.toMap(GenTableEntity::getTableName, e -> e));
            // 填充定义表字段默认信息
            List<GenTableColumnEntity> genTableColumnEntityList = genHelper.initGenTableColumnEntityList(tableEntityMap, dbTableColumnList);
            // 批量保存 定义表字段信息
            genTableColumnService.saveBatch(genTableColumnEntityList);
        }
    }

    @Override
    public void deleteByIds(String tableIds) {
        genTableService.removeByIds(ListUtil.toList(StrUtil.split(tableIds, ",")));
    }

    @Override
    public Map<String, String> previewCode(Long tableId) {
        GenTableBO genTable = genHelper.getGenTableBOById(tableId);
        VelocityInitializer.initVelocity();
        VelocityContext context = VelocityUtils.prepareContext(genTable);
        // 获取模板列表
        List<String> templates = VelocityUtils.getTemplateList(genTable.getTplCategory());
        // 定义返回内容
        Map<String, String> dataMap = new LinkedHashMap<>();
        for (String template : templates) {
            // 渲染模板
            StringWriter sw = new StringWriter();
            Template tpl = Velocity.getTemplate(template, ProjectConstant.UTF8);
            tpl.merge(context, sw);
            dataMap.put(template, sw.toString());
        }
        return dataMap;
    }

    @Override
    public void genCode(Long tableId) {
        GenTableBO genTable = genHelper.getGenTableBOById(tableId);
        VelocityInitializer.initVelocity();
        VelocityContext context = VelocityUtils.prepareContext(genTable);
        // 获取模板列表
        List<String> templates = VelocityUtils.getTemplateList(genTable.getTplCategory());
        // 基本路径
        String basePath = VelocityUtils.getBasePath(genTable);
        for(String template : templates) {
            StringWriter sw = new StringWriter();
            Template tpl = Velocity.getTemplate(template, ProjectConstant.UTF8);
            tpl.merge(context, sw);
            // 获取文件路径
            String path = VelocityUtils.getPath(basePath, genTable, template);
            System.out.println("path-->" + path);
            // 先删除
            FileUtil.del(path);
            // 再添加
            FileUtil.writeString(sw.toString(), path, ProjectConstant.UTF8);
        }
    }

    @Override
    public void genCode(Long tableId, ZipOutputStream zip) {
        GenTableBO genTable = genHelper.getGenTableBOById(tableId);
        VelocityInitializer.initVelocity();
        VelocityContext context = VelocityUtils.prepareContext(genTable);
        // 获取模板列表
        List<String> templates = VelocityUtils.getTemplateList(genTable.getTplCategory());
        try {
            for(String template : templates) {
                StringWriter sw = new StringWriter();
                Template tpl = Velocity.getTemplate(template, ProjectConstant.UTF8);
                tpl.merge(context, sw);
                zip.putNextEntry(new ZipEntry(VelocityUtils.getPath("code/", genTable, template)));
                IoUtil.write(zip, false, sw.toString().getBytes());
                zip.flush();
                zip.closeEntry();
            }
        } catch (Exception e) {
            throw new BusinessException("生成zip异常：" + e.getMessage());
        }
    }


}
